﻿using GriffinNav.GPS;
using GriffinNav.GPS.Logging;
using GriffinNav.Map;
using GriffinNav.Map.Logging;
using System;
using System.IO;

namespace GriffinNav.UI.Logging
{
    internal class ErrorLog
    {
        private string mLogDir;
        private const string mLogFileName = "GriffinNav.UI_errorlog.txt";
        private const string mStackTraceFileName = "GriffinNav.UI_stacktrace.txt";
        private StreamWriter mWriter;

        internal ErrorLog()
        {
            mLogDir = Path.Combine(Global.AppPath, "log");

            if (!Directory.Exists(mLogDir))
            {
                Directory.CreateDirectory(mLogDir);
            }

            FileInfo logFile = new FileInfo(Path.Combine(mLogDir, mLogFileName));

            // check if log file is at or above 128KB in size
            if (logFile.Exists && (logFile.Length / 1024) >= 128)
            {
                logFile.Delete();
            }
        }

        internal void WriteError(string assembly, Exception ex)
        {
            try
            {
                // create string to write to error log
                string line = 
                    DateTime.Now.ToString() + 
                    "\t" + assembly + 
                    "\t" + ex.GetBaseException().GetType().Name + 
                    "\t" + ex.GetBaseException().Message;

                // open error log file
                mWriter = new StreamWriter(new FileStream(Path.Combine(mLogDir, mLogFileName), FileMode.Append, FileAccess.Write, FileShare.Read));

                mWriter.WriteLine(line); // write error info

                // close file
                mWriter.Close();

                // check if stack trace should be logged
                if (Global.Debug)
                {
                    // open stack trace file
                    mWriter = new StreamWriter(new FileStream(Path.Combine(mLogDir, mStackTraceFileName), FileMode.Create, FileAccess.Write, FileShare.Read));

                    mWriter.Write(ex.StackTrace); // write stack trace

                    mWriter.Close(); // close file
                }

                mWriter = null;
            }
            catch
            {
                if (mWriter != null)
                {
                    mWriter.Close();
                }
            }
        }

        internal void WriteError(string assembly, UIException ex)
        {
            try
            {
                // create string to write to error log
                string line =
                    DateTime.Now.ToString() +
                    "\t" + assembly +
                    "\t" + ex.InnerException.GetBaseException().GetType().Name +
                    "\t" + ex.InnerException.GetBaseException().Message;

                // open error log file
                mWriter = new StreamWriter(new FileStream(Path.Combine(mLogDir, mLogFileName), FileMode.Append, FileAccess.Write, FileShare.Read));

                mWriter.WriteLine(line); // write error info

                // close file
                mWriter.Close();

                // check if stack trace should be logged
                if (Global.Debug)
                {
                    // open stack trace file
                    mWriter = new StreamWriter(new FileStream(Path.Combine(mLogDir, mStackTraceFileName), FileMode.Append, FileAccess.Write, FileShare.Read));
                    
                    mWriter.Write(ex.InnerException.StackTrace); // write stack trace

                    mWriter.Close(); // close file
                }

                mWriter = null;
            }
            catch
            {
                if (mWriter != null)
                {
                    mWriter.Close();
                }
            }
        }

        internal void WriteError(string assembly, GPSException ex)
        {
            try
            {
                // create string to write to error log
                string line =
                    DateTime.Now.ToString() +
                    "\t" + assembly +
                    "\t" + ex.InnerException.GetBaseException().GetType().Name +
                    "\t" + ex.InnerException.GetBaseException().Message;

                // open error log file
                mWriter = new StreamWriter(new FileStream(Path.Combine(mLogDir, mLogFileName), FileMode.Append, FileAccess.Write, FileShare.Read));

                mWriter.WriteLine(line); // write error info

                // close file
                mWriter.Close();

                // check if stack trace should be logged
                if (Global.Debug)
                {
                    // open stack trace file
                    mWriter = new StreamWriter(new FileStream(Path.Combine(mLogDir, mStackTraceFileName), FileMode.Create, FileAccess.Write, FileShare.Read));

                    mWriter.Write(ex.InnerException.StackTrace); // write stack trace

                    mWriter.Close(); // close file
                }

                mWriter = null;
            }
            catch
            {
                if (mWriter != null)
                {
                    mWriter.Close();
                }
            }
        }

        internal void WriteError(string assembly, MapException ex)
        {
            try
            {
                // create string to write to error log
                string line =
                    DateTime.Now.ToString() +
                    "\t" + assembly +
                    "\t" + ex.InnerException.GetBaseException().GetType().Name +
                    "\t" + ex.InnerException.GetBaseException().Message;

                // open error log file
                mWriter = new StreamWriter(new FileStream(Path.Combine(mLogDir, mLogFileName), FileMode.Append, FileAccess.Write, FileShare.Read));

                mWriter.WriteLine(line); // write error info

                // close file
                mWriter.Close();

                // check if stack trace should be logged
                if (Global.Debug)
                {
                    // open stack trace file
                    mWriter = new StreamWriter(new FileStream(Path.Combine(mLogDir, mStackTraceFileName), FileMode.Append, FileAccess.Write, FileShare.Read));

                    mWriter.Write(ex.InnerException.StackTrace); // write stack trace

                    mWriter.Close(); // close file
                }

                mWriter = null;
            }
            catch
            {
                if (mWriter != null)
                {
                    mWriter.Close();
                }
            }
        }
    }
}
